﻿using System.Collections.Generic;
using System.Linq;

namespace TakePhotoTogether.Communication.Protocols
{
    public static class DataPacketSlicingExtension
    {
        private static int referenceId = 0;

        public static DataPacket[] SlicingPackets(this DataPacket packet, int numberOfPackets)
        {
            DataPacket[] slicedPackets = new DataPacket[numberOfPackets];

            DataPacket sPacket = null;
            byte[] sliceData = null;

            int newReferenceId = ++referenceId;

            for (int p = 0; p < numberOfPackets; p++)
            {
                sliceData = SliceData(packet.Payload.ToBytes(), p, numberOfPackets);

                sPacket = new DataPacket();
                sPacket.MessageType = (int)MessageTypes.SlicedPacket;
                sPacket.Payload = new SlicedData(packet.MessageType, sliceData, newReferenceId, p, numberOfPackets);
                sPacket.DataSize = sPacket.Payload.ToBytes().Length;

                slicedPackets[p] = sPacket;
            }

            return slicedPackets;
        }

        private static byte[] SliceData(byte[] data, int nPacket, int numberOfPackets)
        {
            int packetSize = (int)(data.Length * 1.0f / numberOfPackets);
            int sDataSize = nPacket == numberOfPackets-1?  (int) (data.Length - (numberOfPackets - 1) * packetSize) : packetSize;
            
            byte[] sData = new byte[sDataSize];

            for (int b = 0; b < sDataSize; b++)
            {
                sData[b] = data[packetSize*nPacket + b];
            }

            return sData;
        }
    }

    public class SlicedPacketAssembly : IRemoteDataListener
    {

        private readonly Dictionary<int, SlicedData[]> slicedDictionary;
        private SocketManager socketManager = null;

        public SlicedPacketAssembly()
        {
            slicedDictionary = new Dictionary<int, SlicedData[]>();

            socketManager = SocketManager.GetSocketManager();
        }

        public SlicedPacketAssembly(SocketManager manager)
        {
            slicedDictionary = new Dictionary<int, SlicedData[]>();

            socketManager = manager;
        }

        public void ReceiveData(PayloadData data)
        {
            if (data is SlicedData)
            {
                SlicedData slicedData = (SlicedData)data;

                SlicedData[] slicedList = null;

                if (slicedDictionary.ContainsKey(slicedData.ReferenceId))
                {
                    slicedList = slicedDictionary[slicedData.ReferenceId];
                }
                else
                {
                    slicedList = new SlicedData[slicedData.NumberOfPackets];
                    slicedDictionary.Add(slicedData.ReferenceId, slicedList);
                }

                slicedList[slicedData.PacketIndex] = slicedData;

                if (slicedList.Where(item => item == null).Count() == 0)
                {
                    slicedDictionary.Remove(slicedData.ReferenceId);

                    byte[] payloadData = assemblyPacketData(slicedList);

                    socketManager.SendDataToListener(payloadData, slicedData.DataType);
                }
            }
        }

        private byte[] assemblyPacketData(SlicedData[] slicedList)
        {
            byte[] data;

            int dataSize = 0;
            int length = slicedList.Length;

            for (int i = 0; i < length; i++)
            {
                dataSize = dataSize + slicedList[i].SlicedBytes.Length;
            }

            data = new byte[dataSize];
            int count = 0;

            for (int i = 0; i < length; i++)
            {
                int byteSize = slicedList[i].SlicedBytes.Length;
                for (int b = 0; b < byteSize; b++)
                {
                    data[count] = slicedList[i].SlicedBytes[b];
                    count++;
                }
            }

            return data;
        }
    }
}
